package com.deep.test.nio;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Iterator;
import java.util.Set;
/**
 * Selector 的基本使用流程
通过 Selector.open() 打开一个 Selector.
将 Channel 注册到 Selector 中, 并设置需要监听的事件(interest set)
不断重复:
调用 select() 方法
调用 selector.selectedKeys() 获取 selected keys
迭代每个 selected key:
*从 selected key 中获取 对应的 Channel 和附加信息(如果有的话)
*判断是哪些 IO 事件已经就绪了, 然后处理它们. 如果是 OP_ACCEPT 事件, 则调用 "SocketChannel clientChannel = ((ServerSocketChannel) key.channel()).accept()" 获取 SocketChannel, 并将它设置为 非阻塞的, 然后将这个 Channel 注册到 Selector 中.
*根据需要更改 selected key 的监听事件.
*将已经处理过的 key 从 selected keys 集合中删除.
 * @author hudepin
 *
 */
public class NioEchoServer implements Runnable{
	public int id = 100001;
	public int bufferSize = 2048;
	private static final int TIMEOUT = 3000;

	public void run() {
		init();
		
	}
	public static void main(String[] args) {
		new Thread(new NioEchoServer()).start();
	}

	private void init() {
		try {
            // 创建通道和选择器
            ServerSocketChannel socketChannel = ServerSocketChannel.open();
            Selector selector = Selector.open();
            InetSocketAddress inetSocketAddress = new InetSocketAddress(
                    InetAddress.getLocalHost(), 7210);
            socketChannel.socket().bind(inetSocketAddress);
            // 设置通道非阻塞 绑定选择器
            socketChannel.configureBlocking(false);
            socketChannel.register(selector, SelectionKey.OP_ACCEPT);
            System.out.println("Server started .... port:7210");
            listener(selector);

        } catch (Exception e) {
            // TODO: handle exception
        }
		
	}

	private void listener(Selector in_selector) {
		try {
			 // 创建一个处理协议的实现类,由它来具体操作  
	        TCPProtocol protocol = new TCPProtocolImpl(bufferSize);  
            while (true) {
            	if(in_selector.select(TIMEOUT)==0){
					System.out.println("等待连接");
					continue;
				}
                //Thread.sleep(1*1000);
                in_selector.select(); // 阻塞 直到有就绪事件为止
                Set<SelectionKey> readySelectionKey = in_selector
                        .selectedKeys();
                Iterator<SelectionKey> it = readySelectionKey.iterator();
                while (it.hasNext()) {
                    SelectionKey selectionKey = it.next();
                    // 判断是哪个事件
                    if (selectionKey.isAcceptable()) {// 客户请求连接
                    	 System.out.println("acceptable");  
                         //该方法在内部，会将interest由OP_ACCEPT改为OP_READ  
                         //如果不执行下面的语句，则会一直是accept状态（初始时设置为了accept），无法进入后面的两个if语句  
                         //console一直打印上面的语句  
                         protocol.handleAccept(selectionKey);  
                    }
                    if (selectionKey.isReadable()) {  
                        // 从客户端读取数据  
                        System.out.println("readable");  
                        protocol.handleRead(selectionKey);  
                    }  
  
                    if (selectionKey.isValid() && selectionKey.isWritable()) {  
                        //客户端连接一次后，N次连续进入该方法  
                        //System.out.println("writable");//连续输出  
                        protocol.handleWrite(selectionKey);  
                    }  
                    if (selectionKey.isConnectable()) {
                        System.out.println(selectionKey.attachment()
                                + " - 连接事件");
                    }
                    // 必须removed 否则会继续存在，下一次循环还会进来,
                    // 注意removed 的位置，针对一个.next() remove一次
                    it.remove(); 
                }
            }
        } catch (Exception e) {
            // TODO: handle exception
            System.out.println("Error - " + e.getMessage());
            e.printStackTrace();
        }

		
	}



}
